/**
 * 实现方块的背景
 * 创建者：Carburn Ashroom
 * 2023.11.13
 */

class BackGround {      // BackGround类是游戏区域

    constructor(width =backWidth, height =backHeight, next =nextPos) {
        this.width = width;
        this.height = height;
        this.matrix = [];
        this.block = null;
        this.nextBlockName = null;
        this.nextBlockBuffer = null;
        this.deleting = -1;
        this.fullLine = [];
        this.gameOver = false;
        this.delayBlock = false;
        this.addScore = 0;
        this.nextX = next[0];
        this.nextY = next[1];
        
        for (let col=0; col != width; ++col) {
            this.matrix.push([]);
            for (let row=0; row != height; ++row) {
                this.matrix[col].push(new Square(col, row));
            }
        }
        this.setBlock();
        this.setBlock();
    }

    draw(context) {     // 绘制
        context.fillStyle = "rgb(" + backColor[0] + "," + backColor[1] + "," + backColor[2] + ")";
        context.fillRect(0, 0, this.width*blkSize, this.height*blkSize);
        for (let m of this.matrix) {
            for (let s of m) {
                if (s.valid) {
                    s.draw(context);
                }
            }
        }
        if (!this.delayBlock) {
            this.block.draw(context);
        }
    }

    setBlock() {        // 创造一个新的俄罗斯方块
        for (let b of this.matrix) {
            if (b[0].valid) {
                this.gameOver = true;
                this.delayBlock = true;
            }
        }
        if (this.nextBlockName != null) {
            this.block = new Block(this.nextBlockName);
        }
        let rand = Math.floor(Math.random()*blkNames.length);
        this.nextBlockName = blkNames[rand];
        this.nextBlockBuffer = new Block(this.nextBlockName);
        this.nextBlockBuffer.movePosTo(this.nextX, this.nextY);
    }

    update() {      // 更新每一帧
        if (this.gameOver) {
            return;
        }
        if (!this.delayBlock) {
            this.block.update();
            if (this.dropFinish()) {
                this.insertBlock();
                if (!this.delayBlock) {
                    this.setBlock();
                }
            }
        }
        let moving = false;
        let finishMove = true;
        for (let col of this.matrix) {
            for (let b of col) {
                moving |= b.moving();
                if (b.valid) {
                    finishMove &= b.update();
                }
            }
        }
        if (this.deleting > 0) {
            --this.deleting;
        }
        else if (this.deleting == 0) {
            this.deleting = -1;
            this.moveAllSquare();
        }
        if (moving && finishMove) {
            this.flushMatrix();
            this.delayBlock = false;
            this.setBlock();
        }
    }
    
    insertBlock() {     // 将俄罗斯方块加入画布中
        let blocks = this.block.absltBlocks;
        for (let b of blocks) {
            this.matrix[b[0]][b[1]-1] = new Square(b[0], b[1]-1, true, this.block.color);
        }
        this.setFullLine();
        this.deleting = -1;
        this.delayBlock = false;
        for (let fl of this.fullLine) {
            this.deleting = blkDelFrame + 1;
            this.delayBlock = true;
            for (let c=0; c!=this.width; ++c) {
                this.matrix[c][fl].del();
            }
        }
    }
    
    dropFinish() {      // 返回老毛子方块是否下落完毕
        let blocks = this.block.absltBlocks;
        for (let b of blocks) {
            if (b[1] < 0) {
                continue;
            }
            else if (b[1] == this.height) {
                return true;
            }
            else if (this.matrix[b[0]][b[1]].valid) {
                return true;
            }
        }
        return false;
    }
    
    blockForbidden(absltBlocks) {       //检测对应方块集是否与已有的方块冲突
        for (let b of absltBlocks) {
            if (this.matrix[b[0]] == undefined || this.matrix[b[0]][b[1]] == undefined) {
                return true;
            }
            if (b[0] == this.width || b[0] < 0 || this.matrix[b[0]][b[1]].valid) {
                return true;
            }
        }
        return false;
    }

    blockMove(offset) {     // 左右移动俄罗斯方块
        let testBlock = this.block.copy();
        for (let b of testBlock.absltBlocks) {
            b[0] += offset;
        }
        if (!this.blockForbidden(testBlock.absltBlocks)) {
            this.block.moveTo(offset);
        }
    }

    blockRotate(offset) {       // 旋转俄罗斯方块
        let testBlock = this.block.copy();
        testBlock.rotate(offset);
        if (!this.blockForbidden(testBlock.absltBlocks)) {
            this.block.rotate(offset);
        }
    }

    setFullLine() {     // 记录所有完全行
        this.fullLine = [];
        for (let r=0; r != this.height; ++r) {
            let full = true;
            for (let c=0; c != this.width; ++c) {
                if (!this.matrix[c][r].valid) {
                    full = false;
                }
            }
            if (full) {
                this.fullLine.push(r);
            }
        }
        let n = this.fullLine.length;
        this.addScore = scMin*(n+0.5*n*(n-1)) + ((n==4) ? scFullBonus : 0);
    }

    getAddScore() {     // 获取加分
        let ads = this.addScore;
        this.addScore = 0;
        return ads;
    }

    flushMatrix() {     // 将运动完毕的方块放到正确的位置
        for (let col in this.matrix) {
            for (let row=this.height; row != 0; ) {
                --row;
                if (this.matrix[col][row].valid) {
                    let pos = this.matrix[col][row].getPos();
                    if (pos[1] != row) {
                        this.matrix[pos[0]][pos[1]] = this.matrix[col][row];
                        this.matrix[col][row] = new Square(col, row);
                    }
                }
            }
        }
    }

    moveAllSquare() {       // 消除完全行后移动所有方块
        for (let row in this.matrix[0]) {
            let drop = 0;
            for (let d of this.fullLine) {
                if (d > row) {
                    ++drop;
                }
            }
            if (drop == 0) {
                continue;
            }
            for (let col of this.matrix) {
                if (col[row].valid) {
                    col[row].drop(drop);
                }
            }
        }
    }

}
